<?php
require_once FORAGE_APP_PATH . '/query/Response.php';
/**
 * This class represents a user query. 
 *
 * @author Rob Young <rob@roryoung.co.uk>
 * @package forage.query
 */
class ForageQuery
{
  /**
   * The raw query string which the user has entered
   *
   * @var string
   */
  private $query_string;

  /**
   * Number of documents to display per page
   *
   * @var int
   */
  private $per_page;

  /**
   * Current page number
   *
   * @var int
   */
  private $page;

  /**
   * Fields which are currently being sorted on
   *
   * @var array
   */
  private $sort_fields;

  /**
   * Registered ForageQueryBehaviour objects
   *
   * @var array
   */
  private $behaviours;

  /**
   * Per query configuration options
   *
   * @var array
   */
  private $config;

  /**
   * Class Constructor
   * Set local defaults such as per_page and page. Also creates a 
   * ForageQueryBehaviourHandler for any query behaviours which may need 
   * to be added.
   *
   */
  public function __construct($config = array())
  {
    $this->per_page    = 10;
    $this->page        = 1;
    $this->sort_fields = array();
    $this->behaviours = new ForageQueryBehaviourHandler();
    $this->config      = $config;
  }

  /**
   * Magic function call method
   * Passes all unhandled calls on to the ForageQueryBehaviourHandler
   *
   * @param string $method
   * @param array $args
   * @return mixed
   */
  public function __call($method, $args)
  {
    return $this->behaviours->__call($method, $args);
  }

  /**
   * Magic accessor
   * Provides access to object properties.
   *
   * @param string $name
   * @return mixed
   */
  public function __get($name)
  {
    switch ($name) {
    case 'query_string':
    case 'per_page':
    case 'page':
    case 'sort_fields':
      return $this->$name;
    case 'start_index':
      return ($this->page-1) * $this->per_page;
    case 'end_index':
      return $this->page * $this->per_page;
    default:
      return $this->behaviours->__get($name);
    }
  }

  /**
   * Setter for query string
   *
   * @param string $query_string
   */
  public function setQueryString($query_string)
  {
    $this->query_string = $query_string;
  }

  /**
   * Set the number of documents to return per page
   *
   * @param int $per_page
   */
  public function setPerPage($per_page)
  {
    ForageValidate::integer($per_page);
    $this->per_page = $per_page;
  }

  /**
   * Set the result page to return
   *
   * @param int $page
   */
  public function setPage($page)
  {
    ForageValidate::integer($page);
    $this->page = $page;
  }

  /**
   * Add a field to sort by
   *
   * @param string $field
   * @param int $sort
   */
  public function addSortField($field, $sort)
  {
    switch ($sort) {
    case SORT_ASC:
    case SORT_DESC:
      $this->sort_fields[$field] = $sort;
      break;
    default:
      throw new InvalidArgumentException("Invalid sort direction [" . $sort . "]");
    }
  }

  public function getConfigOption($name, $default=null)
  {
    return isset($this->config[$name]) ? $this->config[$name] : $default;
  }

  public function setConfigOption($name, $value)
  {
    $this->config[$name] = $value;
  }
}
